/*-------------------------------------------------------------------------
 - Copyright (c) 2024-2025 [XD-AMCC TEAM]
 - [XD-AMCC] is licensed under Mulan PSL v2.
 - You can use this software according to the terms and conditions of the Mulan PSL v2.
 - You may obtain a copy of Mulan PSL v2 at:
 -          http://license.coscl.org.cn/MulanPSL2
 - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
 - OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 - TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 - See the Mulan PSL v2 for more details.
 ------------------------------------------------------------------------*/


/**
 * @file
 * @brief Interface of log facility.
 *
 * @author  WXQ#XDU
 * @date    2024.11
 */

#pragma once

#ifndef AMCC_LOG_H
#define AMCC_LOG_H

#include <stdio.h>
#include "amcc_config.h"

AMCC_DECL_BEGIN


#define SHOW_MSG(fmt, ...)    fprintf(stdout, fmt, ## __VA_ARGS__ )


/**
 * @brief list of all supported log levels.
 */
typedef enum enum_log_level {
    LOG_TRACE =1,  // lowest logLevel
    LOG_DEBUG,
    LOG_INFO,
    LOG_WARN,
    LOG_ERROR,
    LOG_FATAL   // highest logLevel
} EnumLogLevel;

#define LOG_TRACE_ENABLE() (amcc_get_logLevel() <= LOG_TRACE)
#define LOG_DEBUG_ENABLE() (amcc_get_logLevel() <= LOG_DEBUG)
#define LOG_INFO_ENABLE()  (amcc_get_logLevel() <= LOG_INFO)
#define LOG_WARN_ENABLE()  (amcc_get_logLevel() <= LOG_WARN)
#define LOG_ERROR_ENABLE() (amcc_get_logLevel() <= LOG_ERROR)

/**
 * @brief Add(register) new log file.
 *   The old contents of file will be destroyed if log file already exists.
 *
 * @param level     log level for this log file
 * @param filepath  path of log file
 * @return Return 0 on success, otherwise return negative value on failure.
 * @return Return -1 if no space to store this appender,
 * @return Return -2 if the filepath can't been open to write.
 */
extern int  log_add_appender(EnumLogLevel level, const char* filepath);


#define log_trace(...) log_implement(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_debug(...) log_implement(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_info(...)  log_implement(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)
#define log_warn(...)  log_implement(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)
#define log_error(...) log_implement(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_fatal(...) log_implement(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)

#define log_vtrace(...) log_implement_valist(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_vdebug(...) log_implement_valist(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_vinfo(...)  log_implement_valist(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)
#define log_vwarn(...)  log_implement_valist(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)
#define log_verror(...) log_implement_valist(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_vfatal(...) log_implement_valist(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)


//DON'T call this function directly
extern void log_implement(EnumLogLevel level,
                          const char * srcfile, int srcline,
                          const char * format, ...);

//DON'T call this function directly
extern void log_implement_valist(EnumLogLevel level,
                         const char *srcfile, int srcline,
                         const char *format, va_list  valist);


/// ONLY for output very long text without line header
extern void log_without_header(const char * format, ...);


AMCC_DECL_END

#endif // #ifndef AMCC_LOG_H
